package top.korori.api.security;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import top.korori.common.enums.StatusCode;
import top.korori.common.model.Result;
import top.korori.common.utils.JwtUtils;
import top.korori.common.utils.RedisCache;
import top.korori.common.utils.ServletUtils;
import top.korori.sv.constant.AuthConstant;
import top.korori.sv.constant.CacheConstant;
import top.korori.sv.entity.SvUser;
import top.korori.sv.entity.model.LoginUser;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 登录权限拦截器
 */
@Component
public class SvAuthInterceptor implements HandlerInterceptor {

    @Value("${sv.token.secret}")
    public String secret;

    @Value("${sv.token.expireTime}")
    public Long expireTime;

    @Autowired
    private RedisCache redisCache;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        String token = request.getHeader(AuthConstant.HEADER);
        String jwtToken = StrUtil.replace(token, AuthConstant.TOKEN_PREFIX, "");

        DecodedJWT decodedJWT = JwtUtils.verify(jwtToken, secret);

        if (ObjectUtil.isNull(decodedJWT)) {
            ServletUtils.renderString(response, JSON.toJSONString(Result.fail(StatusCode.APPROVE_FAIL)));
            return false;
        }

        String key = CacheConstant.SV_USER_INFO + decodedJWT.getClaim(AuthConstant.JWT_UID).asLong();
        LoginUser<SvUser> loginUser = redisCache.get(key);

        if (ObjectUtil.isNull(loginUser)) {
            ServletUtils.renderString(response, JSON.toJSONString(Result.fail(StatusCode.APPROVE_FAIL)));
            return false;
        }

        //刷新令牌剩余时间
        redisCache.expire(key, expireTime, TimeUnit.MINUTES);
        return true;
    }
}
